package timing.ukulele.auth.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import timing.ukulele.auth.security.user.TimingUserDetailService;
import timing.ukulele.auth.support.RedisOperator;
import timing.ukulele.auth.util.CommonUtil;
import timing.ukulele.auth.vo.CaptchaVO;
import timing.ukulele.common.MobileMsgTemplate;
import timing.ukulele.common.constant.PrefixConstant;
import timing.ukulele.common.data.ResponseData;
import timing.ukulele.common.dictionary.SmsChannelEnum;
import timing.ukulele.common.util.RegexUtil;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

import static timing.ukulele.auth.constant.RedisConstants.*;

/**
 * @author fengxici
 */
@RestController
@Slf4j
@RequestMapping("/common")
@Tag(name = "常规接口", description = "不需要登录的接口")
@ApiResponses(value = {
        @ApiResponse(responseCode = "1000", description = "成功", content = {@Content(mediaType = "application/json")}),
        @ApiResponse(responseCode = "1001", description = "失败", content = {@Content(mediaType = "application/json")}),
        @ApiResponse(responseCode = "3000", description = "业务处理失败", content = {@Content(mediaType = "application/json")})
})
public class CommonController {

    private final String msgTemplate = "【Ukulele】您的登录验证码为%s，请在$s分钟内使用。";
    private final RedisOperator<Integer> integerRedisOperator;
    private final RedisOperator<String> stringRedisOperator;
    private final TimingUserDetailService userDetailService;

    public CommonController(
            RedisOperator<Integer> integerRedisOperator,
            RedisOperator<String> stringRedisOperator,
            TimingUserDetailService userDetailService) {
        this.integerRedisOperator = integerRedisOperator;
        this.stringRedisOperator = stringRedisOperator;
        this.userDetailService = userDetailService;
    }

    @GetMapping("/captcha/password")
    @Operation(summary = "用户名密码登录方式的图片验证码接口", description = "验证码过期时间为15分钟")
    public ResponseData<CaptchaVO> getPasswordCaptcha() {
        return CommonUtil.createCaptcha(stringRedisOperator, IMAGE_CAPTCHA_PREFIX_KEY);
    }

    @GetMapping("/captcha/phone")
    @Operation(summary = "获取短信验证码前的图片验证码接口", description = "验证码过期时间为15分钟")
    public ResponseData<CaptchaVO> getPhoneCaptcha() {
        return CommonUtil.createCaptcha(stringRedisOperator, PHONE_CAPTCHA_PREFIX_KEY);
    }

    @GetMapping("/code/message")
    @Operation(summary = "获取短信验证码接口", description = "验证码过期时间为15分钟")
    @Parameters(value = {
            @Parameter(name = "mobile", description = "手机号", required = true, in = ParameterIn.QUERY),
            @Parameter(name = "captchaId", description = "图片验证码的id", required = true, in = ParameterIn.QUERY),
            @Parameter(name = "captcha", description = "图片验证码", required = true, in = ParameterIn.QUERY),
    })

    public ResponseData<String> getSmsCode(
            @RequestParam("mobile") String mobile,
            @RequestParam("captchaId") String captchaId,
            @RequestParam("captcha") String captcha) {
        if (!(StringUtils.hasText(mobile) && RegexUtil.checkMobileNumber(mobile))) {
            return ResponseData.paramError( "手机号不能为空，且必须是正确的11位格式");
        }
        if (!(StringUtils.hasText(captchaId) && StringUtils.hasText(captcha))) {
            return ResponseData.paramError( "验证码不能为空");
        }
        String cachedCaptcha = stringRedisOperator.get(PHONE_CAPTCHA_PREFIX_KEY + captchaId);
        if (cachedCaptcha == null || !cachedCaptcha.equalsIgnoreCase(captcha)) {
            return ResponseData.paramError( "验证码错误");
        }
        boolean hasUserPhone = userDetailService.hasUserPhone(mobile);
        if (!hasUserPhone) {
            return ResponseData.paramError( "手机号不存在");
        }
        Object phone = integerRedisOperator.get(SMS_CAPTCHA_PREFIX_KEY + mobile);
        if (null == phone) {
            integerRedisOperator.set(SMS_CAPTCHA_PREFIX_KEY + mobile, 1, 3 * 60);
        } else {
            int sendTime = (int) phone;
            if (4 > sendTime) {
                integerRedisOperator.set(SMS_CAPTCHA_PREFIX_KEY + mobile, ++sendTime);
            } else {
                return ResponseData.error(null, "操作太频繁，请稍后再试！");
            }
        }
//        String code = RandomStringUtils.randomNumeric(SPRING_SECURITY_SMS_CODE_LENGTH);
        String code = RandomStringUtils.secure().nextNumeric(SPRING_SECURITY_SMS_CODE_LENGTH);
        log.info("手机验证码----->手机号:" + mobile + ",验证码:" + code);
        String msgContent = String.format(msgTemplate, code, "1");
        MobileMsgTemplate msg = new MobileMsgTemplate(mobile, msgContent, SmsChannelEnum.ALIYUN.getName());

        // todo 发送短信
        stringRedisOperator.set(PrefixConstant.SMS_CODE + mobile, code, DEFAULT_TIMEOUT_SECONDS);
//        return ResponseData.success(code);
        return ResponseData.success();
    }

    @GetMapping("/encrypt/publicKey")
    @Operation(summary = "获取公钥字符串", description = "用于对用户名、密码等加密")
    public ResponseData<String> encryptPublicKey() {
        InputStream ins = this.getClass().getClassLoader().getResourceAsStream("publicKey.txt");
        if (ins == null)
            return ResponseData.error(null, "未找到");
        try {
            BufferedReader tBufferedReader = new BufferedReader(new InputStreamReader(ins));
            StringBuilder tStringBuffer = new StringBuilder();
            String sTempOneLine;
            while ((sTempOneLine = tBufferedReader.readLine()) != null) {
                tStringBuffer.append(sTempOneLine);
            }
            return ResponseData.success(tStringBuffer.toString());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return ResponseData.error(null, "读取错误");
    }
}
